package health_system.health_system.websocket.Server;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import health_system.health_system.websocket.Model.*;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 聊天WebSocket服务器
 * 处理用户间的文字、图片、短视频、语音消息、文件传输及社交功能
 */
@Component
@ServerEndpoint("/ChatMessageServer")
public class ChatMessageServer {
    private static final Logger logger = Logger.getLogger(ChatMessageServer.class.getName());

    // 用户会话映射，保存所有在线用户的WebSocket会话
    private static final Map<String, Session> sessionMap = new ConcurrentHashMap<>();

    // 好友关系映射，保存用户的好友列表
    private static final Map<String, Set<String>> friendsMap = new ConcurrentHashMap<>();

    // JSON序列化工具
    private static final ObjectMapper mapper = new ObjectMapper();

    // 系统消息常量
    private static final String SYSTEM_NAME = "系统";
    private static final String USER_OFFLINE_MESSAGE = "用户当前不在线，消息将在其上线后发送";

    // 消息类型的最大尺寸（字节）
    private static final Map<MessageContentType, Long> MAX_SIZE_LIMITS = new HashMap<>();

    // 用于存储分块消息的临时缓存
    private static final Map<String, Map<Integer, String>> chunkCache = new ConcurrentHashMap<>();
    private static final Map<String, ChatMessage> chunkMetadataCache = new ConcurrentHashMap<>();

    static {
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        // 初始化各类型消息的大小限制
        MAX_SIZE_LIMITS.put(MessageContentType.TEXT, 400* 1024L);          // 4KB
        MAX_SIZE_LIMITS.put(MessageContentType.IMAGE, 50 * 1024 * 1024L); // 10MB
        MAX_SIZE_LIMITS.put(MessageContentType.VIDEO, 50 * 1024 * 1024L); // 50MB
        MAX_SIZE_LIMITS.put(MessageContentType.AUDIO, 50 * 1024 * 1024L);  // 5MB
        MAX_SIZE_LIMITS.put(MessageContentType.FILE, 100 * 1024 * 1024L); // 100MB
    }

    /**
     * 处理WebSocket连接打开事件
     */
    @OnOpen
    public void onOpen(Session session) {
        String sessionId = session.getId();
        logger.info("聊天服务器新连接: " + sessionId);

        // 设置WebSocket会话的消息大小限制
        session.setMaxTextMessageBufferSize(1024 * 1024 * 8); // 8MB text buffer
        session.setMaxBinaryMessageBufferSize(1024 * 1024 * 8); // 8MB binary buffer

        Optional.ofNullable(extractUsernameFromQueryString(session.getQueryString()))
            .ifPresentOrElse(
                username -> {
                    sessionMap.put(username, session);
                    logger.info("用户上线: " + username);

                    // 如果是新用户，初始化好友列表
                    friendsMap.putIfAbsent(username, ConcurrentHashMap.newKeySet());

                    // 在测试环境中，自动添加常用测试用户为好友关系
                    addTestFriends(username);

                    // 通知该用户的好友其已上线
                    notifyFriendsOfStatusChange(username, true);

                    // 发送离线消息（实际实现中需要从数据库获取）
                    sendOfflineMessages(username);
                },
                () -> logger.warning("无效的用户名参数: " + sessionId)
            );
    }

    /**
     * 处理WebSocket连接关闭事件
     */
    @OnClose
    public void onClose(Session session) {
        Optional.ofNullable(extractUsernameFromQueryString(session.getQueryString()))
            .ifPresent(username -> {
                if (sessionMap.containsKey(username)) {
                    logger.info(username + " 已离线");
                    sessionMap.remove(username);

                    // 通知该用户的好友其已离线
                    notifyFriendsOfStatusChange(username, false);
                }
            });
    }

    /**
     * 处理WebSocket错误事件
     */
    @OnError
    public void onError(Session session, Throwable error) {
        String sessionId = session.getId();
        String username = extractUsernameFromQueryString(session.getQueryString());
        logger.log(Level.SEVERE, "WebSocket错误 " + sessionId +
                  (username != null ? " (用户: " + username + ")" : ""), error);
    }

    /**
     * 处理接收到的WebSocket消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        if (message == null || message.isEmpty()) {
            logger.warning("收到空消息: " + session.getId());
            return;
        }

        logger.fine("收到消息: " + message);

        try {
            ChatMessage chatMessage = mapper.readValue(message, ChatMessage.class);
            String messageType = chatMessage.getType();
            String fromUser = chatMessage.getFromUser();

            // 处理分块消息
            if ("chunk_metadata".equals(messageType)) {
                handleChunkMetadata(chatMessage);
                return;
            } else if ("chunk".equals(messageType)) {
                handleMessageChunk(chatMessage);
                return;
            }

            MessageType type = MessageType.fromString(messageType);

            if (type == null || fromUser == null) {
                logger.warning("无效的消息格式: 缺少必要字段");
                return;
            }

            switch (type) {
                case CHAT_MESSAGE:
                    handleChatMessage(chatMessage);
                    break;
                case FRIEND_REQUEST:
                    handleFriendRequest(chatMessage);
                    break;
                case FRIEND_RESPONSE:
                    handleFriendResponse(chatMessage);
                    break;
                case SOCIAL_POST:
                    handleSocialPost(chatMessage);
                    break;
                case SOCIAL_INTERACTION:
                    handleSocialInteraction(chatMessage);
                    break;
                case TYPING_INDICATOR:
                    handleTypingIndicator(chatMessage);
                    break;
                case READ_RECEIPT:
                    handleReadReceipt(chatMessage);
                    break;
                case MEDIA_TRANSFER:
                    handleMediaTransfer(chatMessage);
                    break;
                case MEDIA_TRANSFER_START:
                    handleMediaTransferStart(chatMessage);
                    break;
                case MEDIA_TRANSFER_COMPLETE:
                    handleMediaTransferComplete(chatMessage);
                    break;
                default:
                    logger.warning("未处理的消息类型: " + type);
            }
        } catch (Exception e) {
            logger.log(Level.SEVERE, "处理消息时出错: " + e.getMessage(), e);
        }
    }

    /**
     * 处理聊天消息
     */
    private void handleChatMessage(ChatMessage message) throws IOException {
        String toUser = message.getToUser();
        String fromUser = message.getFromUser();

        // 验证消息大小是否符合限制
        if (!validateMessageSize(message)) {
            sendErrorToUser(fromUser, "消息超出大小限制");
            return;
        }

        // 检查是否来自测试页面的消息(通常测试页面的用户名是数字或特定格式)
        boolean isTestMessage = isTestUser(fromUser) || isTestUser(toUser);

        // 验证发送者和接收者是否为好友关系（测试消息可以跳过好友验证）
        if (!isTestMessage && !areFriends(fromUser, toUser)) {
            sendErrorToUser(fromUser, "无法发送消息，对方不是您的好友");
            return;
        }

        // 生成消息ID和时间戳
        message.setMessageId(generateMessageId());
        message.setTimestamp(System.currentTimeMillis());

        // 标记消息为未读
        message.setRead(false);

        Session toUserSession = sessionMap.get(toUser);

        if (toUserSession != null && toUserSession.isOpen()) {
            // 接收者在线，直接发送消息
            send(toUserSession, message);

            // 发送发送成功的确认给发送者
            sendDeliveryConfirmation(fromUser, message.getMessageId(), DeliveryStatus.SENT);
        } else {
            // 接收者不在线，存储离线消息
            // 注：实际实现中应存储到数据库，这里仅发送通知
            logger.info("用户" + toUser + "不在线，消息将稍后发送");

            // 发送离线通知给发送者
            sendDeliveryConfirmation(fromUser, message.getMessageId(), DeliveryStatus.PENDING);
        }
    }

    /**
     * 判断是否是测试用户
     */
    private boolean isTestUser(String username) {
        // 测试用户通常是数字ID或特定格式
        return username != null && (
            username.matches("\\d+") ||  // 纯数字ID
            username.startsWith("test") ||
            username.startsWith("user")
        );
    }

    /**
     * 处理好友请求
     */
    private void handleFriendRequest(ChatMessage message) throws IOException {
        String fromUser = message.getFromUser();
        String toUser = message.getToUser();

        Session toUserSession = sessionMap.get(toUser);

        if (toUserSession != null && toUserSession.isOpen()) {
            // 用户在线，发送好友请求
            send(toUserSession, message);
        } else {
            // 用户不在线，存储离线请求
            // 注：实际实现中应存储到数据库
            sendSystemMessageToUser(fromUser, "用户" + toUser + "当前不在线，请求将在其上线后发送");
        }
    }

    /**
     * 处理好友请求响应
     */
    private void handleFriendResponse(ChatMessage message) throws IOException {
        String fromUser = message.getFromUser();
        String toUser = message.getToUser();
        Boolean accepted = Boolean.parseBoolean(message.getContent());

        if (accepted) {
            // 接受好友请求，更新好友关系
            addFriend(fromUser, toUser);

            // 通知双方好友关系已建立
            sendSystemMessageToUser(fromUser, "您已添加 " + toUser + " 为好友");
            sendSystemMessageToUser(toUser, fromUser + " 已接受您的好友请求");
        } else {
            // 拒绝好友请求，通知发送方
            sendSystemMessageToUser(toUser, fromUser + " 拒绝了您的好友请求");
        }
    }

    /**
     * 处理朋友圈发布
     */
    private void handleSocialPost(ChatMessage message) throws IOException {
        String fromUser = message.getFromUser();

        // 生成朋友圈消息ID和时间戳
        message.setMessageId(generateMessageId());
        message.setTimestamp(System.currentTimeMillis());

        // 处理媒体内容（实际实现中应存储到服务器）
        if (!MessageContentType.TEXT.getValue().equals(message.getContentType())) {
            // 处理媒体文件存储和URL生成
            String mediaUrl = processAndStoreMediaContent(message);
            message.setContent(mediaUrl);
        }

        // 获取发布者的所有好友
        Set<String> friends = friendsMap.getOrDefault(fromUser, Collections.emptySet());

        // 通知所有在线好友有新动态
        for (String friend : friends) {
            Session friendSession = sessionMap.get(friend);
            if (friendSession != null && friendSession.isOpen()) {
                send(friendSession, message);
            }
            // 对不在线的好友，实际实现中应存储到数据库，待上线后通知
        }

        // 发送确认给发布者
        sendSystemMessageToUser(fromUser, "朋友圈动态已发布");
    }

    /**
     * 处理社交互动（点赞、评论等）
     */
    private void handleSocialInteraction(ChatMessage message) throws IOException {
        String fromUser = message.getFromUser();
        String toUser = message.getToUser();
        String postId = message.getRelatedMessageId();
        SocialInteractionType interactionType = SocialInteractionType.fromString(message.getContent());

        if (interactionType == null || postId == null) {
            sendErrorToUser(fromUser, "无效的社交互动请求");
            return;
        }

        // 生成互动ID和时间戳
        message.setMessageId(generateMessageId());
        message.setTimestamp(System.currentTimeMillis());

        // 通知帖子所有者有新互动
        Session toUserSession = sessionMap.get(toUser);
        if (toUserSession != null && toUserSession.isOpen()) {
            send(toUserSession, message);
        }
        // 对不在线的用户，实际实现中应存储到数据库，待上线后通知

        // 发送确认给互动者
        switch (interactionType) {
            case LIKE:
                sendSystemMessageToUser(fromUser, "您已点赞该动态");
                break;
            case COMMENT:
                sendSystemMessageToUser(fromUser, "您的评论已发布");
                break;
            case SHARE:
                sendSystemMessageToUser(fromUser, "您已成功分享该动态");
                break;
        }
    }

    /**
     * 处理正在输入指示器
     */
    private void handleTypingIndicator(ChatMessage message) throws IOException {
        String toUser = message.getToUser();

        Session toUserSession = sessionMap.get(toUser);
        if (toUserSession != null && toUserSession.isOpen()) {
            // 直接转发指示器消息给接收者
            send(toUserSession, message);
        }
    }

    /**
     * 处理已读回执
     */
    private void handleReadReceipt(ChatMessage message) throws IOException {
        String toUser = message.getToUser();
        String messageId = message.getRelatedMessageId();

        if (messageId == null) {
            return;
        }

        Session toUserSession = sessionMap.get(toUser);
        if (toUserSession != null && toUserSession.isOpen()) {
            // 发送已读回执给原消息发送者
            message.setRead(true);
            send(toUserSession, message);
        }
        // 对不在线的用户，实际实现中应存储到数据库
    }

    /**
     * 处理媒体传输消息
     * 处理大文件的分块传输
     */
    private void handleMediaTransfer(ChatMessage message) throws IOException {
        String fromUser = message.getFromUser();
        String toUser = message.getToUser();

        // 如果是多媒体聊天内容（图片、视频、语音等），执行端到端转发，不存储
        if (!MessageContentType.TEXT.getValue().equals(message.getContentType()) &&
            !message.isRelatedToSocialPost()) {

            Session toUserSession = sessionMap.get(toUser);
            if (toUserSession != null && toUserSession.isOpen()) {
                // 直接转发给接收者
                send(toUserSession, message);

                // 发送传输确认给发送者
                sendDeliveryConfirmation(fromUser, message.getMessageId(), DeliveryStatus.SENT);
            } else {
                // 接收者不在线，返回错误
                sendErrorToUser(fromUser, "用户" + toUser + "不在线，无法传输媒体内容");
            }
        }
    }

    /**
     * 从查询字符串中提取用户名
     */
    private String extractUsernameFromQueryString(String queryString) {
        if (queryString == null || !queryString.contains("username=")) {
            return null;
        }

        String[] parts = queryString.split("username=");
        if (parts.length < 2) {
            return null;
        }

        String username = parts[1];
        int ampIndex = username.indexOf('&');
        if (ampIndex != -1) {
            username = username.substring(0, ampIndex);
        }

        return username;
    }

    /**
     * 发送消息到指定会话
     */
    private void send(Session session, ChatMessage message) {
        try {
            String jsonMessage = mapper.writeValueAsString(message);
            send(session, jsonMessage);
        } catch (JsonProcessingException e) {
            logger.log(Level.SEVERE, "序列化消息失败", e);
        }
    }

    /**
     * 发送文本消息到指定会话
     */
    private void send(Session session, String message) {
        if (session == null || !session.isOpen()) {
            logger.warning("尝试向无效会话发送消息");
            return;
        }

        try {
            logger.fine("发送消息: " + message);
            // 检查消息大小
            if (message.length() > session.getMaxTextMessageBufferSize()) {
                logger.warning("消息大小超过会话限制，尝试分块发送");
                sendLargeMessage(session, message);
            } else {
                synchronized (session) {
                    session.getBasicRemote().sendText(message);
                }
            }
        } catch (IOException e) {
            logger.log(Level.SEVERE, "发送消息时出错", e);
        }
    }

    /**
     * 发送系统消息给指定用户
     */
    private void sendSystemMessageToUser(String username, String content) {
        Session userSession = sessionMap.get(username);
        if (userSession != null && userSession.isOpen()) {
            ChatMessage systemMessage = new ChatMessage();
            systemMessage.setType(MessageType.SYSTEM_NOTIFICATION.getValue());
            systemMessage.setFromUser(SYSTEM_NAME);
            systemMessage.setToUser(username);
            systemMessage.setContentType(MessageContentType.TEXT.getValue());
            systemMessage.setContent(content);
            systemMessage.setTimestamp(System.currentTimeMillis());
            systemMessage.setMessageId(generateMessageId());

            send(userSession, systemMessage);
        }
    }

    /**
     * 发送错误消息给指定用户
     */
    private void sendErrorToUser(String username, String errorMessage) {
        Session userSession = sessionMap.get(username);
        if (userSession != null && userSession.isOpen()) {
            ChatMessage errorMsg = new ChatMessage();
            errorMsg.setType(MessageType.ERROR.getValue());
            errorMsg.setFromUser(SYSTEM_NAME);
            errorMsg.setToUser(username);
            errorMsg.setContentType(MessageContentType.TEXT.getValue());
            errorMsg.setContent(errorMessage);
            errorMsg.setTimestamp(System.currentTimeMillis());

            send(userSession, errorMsg);
        }
    }

    /**
     * 发送传递确认消息
     */
    private void sendDeliveryConfirmation(String username, String messageId, DeliveryStatus status) {
        Session userSession = sessionMap.get(username);
        if (userSession != null && userSession.isOpen()) {
            ChatMessage confirmationMsg = new ChatMessage();
            confirmationMsg.setType(MessageType.DELIVERY_STATUS.getValue());
            confirmationMsg.setFromUser(SYSTEM_NAME);
            confirmationMsg.setToUser(username);
            confirmationMsg.setContentType(MessageContentType.TEXT.getValue());
            confirmationMsg.setRelatedMessageId(messageId);
            confirmationMsg.setContent(status.getValue());
            confirmationMsg.setTimestamp(System.currentTimeMillis());

            send(userSession, confirmationMsg);
        }
    }

    /**
     * 通知好友状态变化（上线/离线）
     */
    private void notifyFriendsOfStatusChange(String username, boolean isOnline) {
        Set<String> friends = friendsMap.getOrDefault(username, Collections.emptySet());

        for (String friend : friends) {
            Session friendSession = sessionMap.get(friend);
            if (friendSession != null && friendSession.isOpen()) {
                ChatMessage statusMsg = new ChatMessage();
                statusMsg.setType(MessageType.FRIEND_STATUS.getValue());
                statusMsg.setFromUser(username);
                statusMsg.setToUser(friend);
                statusMsg.setContentType(MessageContentType.TEXT.getValue());
                statusMsg.setContent(isOnline ? "online" : "offline");
                statusMsg.setTimestamp(System.currentTimeMillis());

                send(friendSession, statusMsg);
            }
        }
    }

    /**
     * 检验消息大小是否超过限制
     */
    private boolean validateMessageSize(ChatMessage message) {
        MessageContentType contentType = MessageContentType.fromString(message.getContentType());
        if (contentType == null) {
            return false;
        }

        Long maxSize = MAX_SIZE_LIMITS.get(contentType);

        // 针对Base64编码的内容估算实际大小
        if (message.getContent() != null && contentType != MessageContentType.TEXT) {
            // Base64编码的字符串长度大约是原始二进制大小的4/3
            long estimatedSize = (long) (message.getContent().length() * 0.75);
            return maxSize == null || estimatedSize <= maxSize;
        }

        return true;
    }

    /**
     * 检查两个用户是否为好友关系
     */
    private boolean areFriends(String user1, String user2) {
        Set<String> user1Friends = friendsMap.getOrDefault(user1, Collections.emptySet());
        return user1Friends.contains(user2);
    }

    /**
     * 添加好友关系（双向）
     */
    private void addFriend(String user1, String user2) {
        friendsMap.computeIfAbsent(user1, k -> ConcurrentHashMap.newKeySet()).add(user2);
        friendsMap.computeIfAbsent(user2, k -> ConcurrentHashMap.newKeySet()).add(user1);
    }

    /**
     * 发送离线消息
     */
    private void sendOfflineMessages(String username) {
        // 实际实现中应从数据库获取离线消息并发送
        // 这里仅作为示例
    }

    /**
     * 判断消息是否为社交媒体内容（允许存储）
     */
    private boolean isSocialMedia(ChatMessage message) {
        String type = message.getType();
        return MessageType.SOCIAL_POST.getValue().equals(type) ||
               MessageType.SOCIAL_INTERACTION.getValue().equals(type);
    }

    /**
     * 处理并存储媒体内容，返回URL
     * 注：仅处理朋友圈和头像等允许存储的媒体
     */
    private String processAndStoreMediaContent(ChatMessage message) {
        // 实际实现中应将Base64内容解码并存储到文件系统
        // 然后生成访问URL

        String userId = message.getFromUser();
        String contentType = message.getContentType();
        String timestamp = String.valueOf(System.currentTimeMillis());

        // 示例URL格式，实际实现应该基于实际存储路径生成
        return "/media/" + contentType + "/" + userId + "/" + timestamp + "/" + message.getMessageId();
    }

    /**
     * 生成唯一消息ID
     */
    private String generateMessageId() {
        return UUID.randomUUID().toString();
    }

    /**
     * 处理分块消息的元数据
     */
    private void handleChunkMetadata(ChatMessage message) {
        String messageId = message.getMessageId();
        Integer totalChunks = message.getTotalChunks();

        if (messageId == null || totalChunks == null || totalChunks <= 0) {
            logger.warning("无效的分块元数据");
            return;
        }

        // 存储元数据和初始化分块缓存
        chunkMetadataCache.put(messageId, message);
        chunkCache.put(messageId, new HashMap<>());

        logger.info("收到分块消息元数据: ID=" + messageId + ", 总块数=" + totalChunks);
    }

    /**
     * 处理单个消息分块
     */
    private void handleMessageChunk(ChatMessage message) {
        String messageId = message.getMessageId();
        Integer chunkIndex = message.getChunkIndex();
        Integer totalChunks = message.getTotalChunks();

        // 日志输出消息内容，帮助调试
        logger.fine("接收到分块消息: " + message.getType() + ", messageId=" + messageId);

        if (messageId == null || chunkIndex == null || totalChunks == null) {
            logger.warning("无效的分块消息: 缺少必要的字段");
            return;
        }

        // 优先从chunk字段获取内容，如果为空则使用content字段
        String chunk = message.getChunk();
        if (chunk == null) {
            chunk = message.getContent();
        }

        // 如果内容为空，则记录错误并返回
        if (chunk == null) {
            logger.warning("无效的分块消息: 内容为空");
            return;
        }

        Map<Integer, String> chunks = chunkCache.get(messageId);
        if (chunks == null) {
            logger.warning("未找到分块元数据，忽略分块: " + messageId);
            return;
        }

        // 存储当前分块
        chunks.put(chunkIndex, chunk);

        logger.fine("收到分块 " + chunkIndex + "/" + totalChunks + " 用于消息 " + messageId);

        // 检查是否所有分块都已收到
        if (chunks.size() == totalChunks) {
            try {
                // 所有分块已收到，重组完整消息
                reassembleAndProcessChunkedMessage(messageId);
            } catch (Exception e) {
                logger.log(Level.SEVERE, "重组分块消息失败: " + e.getMessage(), e);
            }
        }
    }

    /**
     * 重组并处理分块消息
     */
    private void reassembleAndProcessChunkedMessage(String messageId) throws IOException {
        Map<Integer, String> chunks = chunkCache.get(messageId);
        ChatMessage metadata = chunkMetadataCache.get(messageId);

        if (chunks == null || metadata == null) {
            logger.warning("无法找到需要重组的分块消息数据: " + messageId);
            return;
        }

        // 按顺序重组所有分块
        StringBuilder fullMessageStr = new StringBuilder();
        for (int i = 0; i < chunks.size(); i++) {
            String chunk = chunks.get(i);
            if (chunk == null) {
                logger.warning("分块 " + i + " 缺失，无法重组消息: " + messageId);
                return;
            }
            fullMessageStr.append(chunk);
        }

        try {
            // 解析完整消息
            ChatMessage fullMessage = mapper.readValue(fullMessageStr.toString(), ChatMessage.class);

            // 处理重组后的完整消息
            MessageType type = MessageType.fromString(metadata.getOriginalType());

            logger.info("成功重组分块消息: ID=" + messageId + ", 类型=" + type);

            // 根据消息类型进行处理
            if (type != null) {
                switch (type) {
                    case CHAT_MESSAGE:
                        handleChatMessage(fullMessage);
                        break;
                    case MEDIA_TRANSFER:
                        handleMediaTransfer(fullMessage);
                        break;
                    default:
                        logger.warning("未处理的重组消息类型: " + type);
                }
            }
        } finally {
            // 清理缓存
            chunkCache.remove(messageId);
            chunkMetadataCache.remove(messageId);
        }
    }

    /**
     * 处理媒体传输开始事件
     */
    private void handleMediaTransferStart(ChatMessage message) throws IOException {
        String fromUser = message.getFromUser();
        String toUser = message.getToUser();
        String fileId = message.getFileId();

        logger.info("开始媒体传输: 文件ID=" + fileId + ", 从=" + fromUser + ", 到=" + toUser);

        // 验证发送者和接收者是否为好友关系
        if (!areFriends(fromUser, toUser)) {
            sendErrorToUser(fromUser, "无法发送文件，对方不是您的好友");
            return;
        }

        Session toUserSession = sessionMap.get(toUser);
        if (toUserSession != null && toUserSession.isOpen()) {
            // 接收者在线，转发开始传输的通知
            send(toUserSession, message);
        } else {
            // 接收者不在线，通知发送者
            sendSystemMessageToUser(fromUser, USER_OFFLINE_MESSAGE);
        }
    }

    /**
     * 处理媒体传输完成事件
     */
    private void handleMediaTransferComplete(ChatMessage message) throws IOException {
        String fromUser = message.getFromUser();
        String toUser = message.getToUser();
        String fileId = message.getFileId();

        logger.info("媒体传输完成: 文件ID=" + fileId);

        Session toUserSession = sessionMap.get(toUser);
        if (toUserSession != null && toUserSession.isOpen()) {
            // 接收者在线，转发完成通知
            send(toUserSession, message);
        }

        // 通知发送者传输完成
        sendSystemMessageToUser(fromUser, "文件 " + message.getFileName() + " 已成功发送");
    }

    /**
     * 聊天消息模型
     */









    /**
     * 分块发送大消息
     */
    private void sendLargeMessage(Session session, String message) {
        if (session == null || !session.isOpen()) {
            return;
        }

        try {
            // 分块大小
            final int CHUNK_SIZE = 64 * 1024; // 64KB

            // 计算分块数
            int totalChunks = (int) Math.ceil((double) message.length() / CHUNK_SIZE);
            String messageId = "server_" + generateMessageId();

            // 发送元数据
            ChatMessage metadataMessage = new ChatMessage();
            metadataMessage.setType("chunk_metadata");
            metadataMessage.setTotalChunks(totalChunks);
            metadataMessage.setMessageId(messageId);

            String metadataJson = mapper.writeValueAsString(metadataMessage);
            synchronized (session) {
                session.getBasicRemote().sendText(metadataJson);
            }

            // 分块发送
            for (int i = 0; i < totalChunks; i++) {
                int start = i * CHUNK_SIZE;
                int end = Math.min((i + 1) * CHUNK_SIZE, message.length());
                String chunk = message.substring(start, end);

                ChatMessage chunkMessage = new ChatMessage();
                chunkMessage.setType("chunk");
                chunkMessage.setMessageId(messageId);
                chunkMessage.setChunkIndex(i);
                chunkMessage.setTotalChunks(totalChunks);
                chunkMessage.setContent(chunk);

                String chunkJson = mapper.writeValueAsString(chunkMessage);
                synchronized (session) {
                    session.getBasicRemote().sendText(chunkJson);
                    // 小延迟防止拥塞
                    Thread.sleep(50);
                }
            }
        } catch (Exception e) {
            logger.log(Level.SEVERE, "分块发送消息时出错", e);
        }
    }

    /**
     * 为测试用户自动添加好友关系
     */
    private void addTestFriends(String username) {
        // 常用测试用户ID
        List<String> testUsers = Arrays.asList("1", "2", "3", "test", "user1", "user2");

        // 如果是测试用户，互相添加为好友
        if (testUsers.contains(username)) {
            for (String testUser : testUsers) {
                // 不需要和自己成为好友
                if (!testUser.equals(username)) {
                    addFriend(username, testUser);
                    logger.info("测试环境：自动添加好友关系 " + username + " <-> " + testUser);
                }
            }
        }
    }
}